<!doctype html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title>酱酱好棒</title>
	<style>
		body{margin: 0;padding: 0;}
		#app{
			display: flex;
			justify-content: center;
			align-items: center;
			width: 100vw;
			height: 100vh;
		}
		.jiangjiang{color: red;}
		body > canvas{position: fixed; top: 0;right: 0;bottom: 0;left: 0; z-index: -1; width: 100vw; height: 100vh;}
	</style>
</head>
<body>
<div id="app">
	<h1 class="jiangjiang">酱酱好棒</h1>
</div>
<script src="../../data/lib/jquery.min.js"></script>
<script src="../../data/lib/three.min.js"></script>
<script src="../../data/lib/TweenMax.min.js"></script>
<script>
  // a 标签再手机中不跳转的问题
  function aClick (tag) {
    var url = $(tag).attr('href')
    var target = $(tag).attr('target')
    window.open(url, target)
  }
</script>
<script>
  var isMouseDown = false
  var emptySlot = 'emptySlot', planeTop = 'planeTop', planeBottom = 'planeBottom'
  var camera, scene, renderer
  var mouse = {x: 0, y: 0}
  var camPos = {x: 0, y: 0, z: 10}
  var sw = window.innerWidth, sh = window.innerHeight
  var cols = 50
  var rows = 20
  var gap = 20
  //方块的长宽高
  var size = {
    width: 100,
    height: 20,
    depth: 150,
  }
  //空间高度
  var planeOffset = 300
  var allRowsDepth = rows * (size.depth + gap)
  var allColsWidth = cols * (size.depth + gap)
  //方块默认速度
  var speedNormal = 2
  //方块点击速度
  var speedFast = 50
  var speed = speedNormal
  var boxes = {
    planeBottom: [],
    planeTop: []
  }
  var boxes1d = []
  
  function num (min, max) {
    return Math.random() * (max - min) + min
  }
  
  function draw (props) {
    var colours = {
      slow: {
        r: num(0, 0.2),
        g: num(0.5, 0.9),
        b: num(0.3, 0.7)
      },
      fast: {
        r: num(0.9, 1.0),
        g: num(0.1, 0.7),
        b: num(0.2, 0.5)
      }
    }
    var uniforms = {
      r: {type: 'f', value: colours.slow.r},
      g: {type: 'f', value: colours.slow.g},
      b: {type: 'f', value: colours.slow.b},
      distanceX: {type: 'f', value: 1.0},
      distanceZ: {type: 'f', value: 1.0},
      pulse: {type: 'f', value: 0},
      speed: {type: 'f', value: speed},
    }
    var material = new THREE.ShaderMaterial({
      uniforms: uniforms,
      vertexShader: vertexShader,
      fragmentShader: fragmentShader
    })
    var geometry = new THREE.BoxGeometry(props.width, props.height, props.depth)
    var object = new THREE.Mesh(geometry, material)
    object.colours = colours
    return object
  }
  
  function init () {
    scene = new THREE.Scene()
    camera = new THREE.PerspectiveCamera(100, sw / sh, 1, 10000)
    scene.add(camera)
    renderer = new THREE.WebGLRenderer({antialias: true})
    renderer.setSize(sw, sh)
    for (var j = 0, jl = rows; j < jl; j++) {
      boxes.planeBottom[j] = []
      boxes.planeTop[j] = []
      for (var i = 0, il = cols; i < il; i++) {
        boxes.planeBottom[j][i] = emptySlot
        boxes.planeTop[j][i] = emptySlot
      }
      
    }
    
    function createBox () {
      var xi = Math.floor(Math.random() * cols),
        xai = xi
      var yi = Math.random() > 0.5 ? 1 : -1,
        yai = yi === -1 ? planeBottom : planeTop
      var zi = Math.floor(Math.random() * rows),
        zai = zi
      var x = (xi - cols / 2) * (size.width + gap)
      var y = yi * planeOffset
      var z = zi * (size.depth + gap)
      if (boxes[yai][zai][xai] === emptySlot) {
        var box = draw(size)
        box.position.y = y
        box.isWarping = false
        box.offset = {
          x: x,
          z: 0
        }
        box.posZ = z
        boxes[yai][zai][xai] = box
        boxes1d.push(box)
        scene.add(box)
      }
    }
    
    for (var i = 0, il = rows * cols; i < il; i++) {
      createBox()
    }
    
    document.body.appendChild(renderer.domElement)
    
    function listen (eventNames, callback) {
      for (var i = 0; i < eventNames.length; i++) {
        window.addEventListener(eventNames[i], callback)
      }
    }
    
    listen(['resize'], function (e) {
      sw = window.innerWidth
      sh = window.innerHeight
      camera.aspect = sw / sh
      camera.updateProjectionMatrix()
      renderer.setSize(sw, sh)
    })
    listen(['mousedown', 'touchstart'], function (e) {
      e.preventDefault()
      isMouseDown = true
    })
    listen(['mousemove', 'touchmove'], function (e) {
      e.preventDefault()
      if (e.changedTouches && e.changedTouches[0]) e = e.changedTouches[0]
      mouse.x = (e.clientX / sw) * 2 - 1
      mouse.y = -(e.clientY / sh) * 2 + 1
    })
    listen(['mouseup', 'touchend'], function (e) {
      e.preventDefault()
      isMouseDown = false
    })
    render(0)
  }
  
  function move (x, y, z) {
    var box = boxes[y][z][x]
    if (box !== emptySlot) {
      box.position.x = box.offset.x
      box.position.z = box.offset.z + box.posZ
      if (box.position.z > 0) {
        box.posZ -= allRowsDepth
      }
      if (!box.isWarping && Math.random() > 0.999) {
        
        var dir = Math.floor(Math.random() * 5), xn = x, zn = z, yn = y, yi = 0, xo = 0, zo = 0
        switch (dir) {
          case 0 :
            xn++
            xo = 1
            break
          case 1 :
            xn--
            xo = -1
            break
          case 2 :
            zn++
            zo = 1
            break
          case 3 :
            zn--
            zo = -1
            break
          case 4 :
            yn = (y === planeTop) ? planeBottom : planeTop
            yi = (y === planeTop) ? -1 : 1
            break
        }
        if (boxes[yn][zn] && boxes[yn][zn][xn] === emptySlot) {
          boxes[y][z][x] = emptySlot
          box.isWarping = true
          boxes[yn][zn][xn] = box
          if (dir === 4) {
            TweenMax.to(box.position, 0.5, {
              y: yi * planeOffset
            })
          } else {
            TweenMax.to(box.offset, 0.5, {
              x: box.offset.x + xo * (size.width + gap),
              z: box.offset.z + zo * (size.depth + gap),
            })
          }
          TweenMax.to(box.offset, 0.6, {
            onComplete: function () {
              box.isWarping = false
            }
          })
          
        }
      }
      
    }
  }
  
  function render (time) {
    speed -= (speed - (isMouseDown ? speedFast : speedNormal)) * 0.05
    var box
    for (var b = 0, bl = boxes1d.length; b < bl; b++) {
      box = boxes1d[b]
      box.posZ += speed
      var distanceZ = 1 - ((allRowsDepth - box.posZ) / (allRowsDepth) - 1)
      box.material.uniforms.distanceZ.value = distanceZ
      var distanceX = 1 - (Math.abs(box.position.x)) / (allColsWidth / 3)
      box.material.uniforms.distanceX.value = distanceX
      var colour = isMouseDown ? box.colours.fast : box.colours.slow
      box.material.uniforms.r.value -= (box.material.uniforms.r.value - colour.r) * 0.1
      box.material.uniforms.g.value -= (box.material.uniforms.g.value - colour.g) * 0.1
      box.material.uniforms.b.value -= (box.material.uniforms.b.value - colour.b) * 0.1
      var currentSpeed = (speed - speedNormal) / (speedFast - speedNormal)
      box.material.uniforms.speed.value = currentSpeed
      if (Math.random() > (0.99995 - currentSpeed * 0.005)) {
        box.material.uniforms.pulse.value = 1
      }
      box.material.uniforms.pulse.value -= box.material.uniforms.pulse.value * 0.1 / (currentSpeed + 1)
    }
    for (var j = 0, jl = rows; j < jl; j++) { // iterate through rows: z
      for (var i = 0, il = cols; i < il; i++) { // iterate throw cols: x
        move(i, planeBottom, j)
        move(i, planeTop, j)
      }
      
    }
    
    camPos.x -= (camPos.x - mouse.x * 400) * 0.02
    camPos.y -= (camPos.y - mouse.y * 150) * 0.05
    camPos.z = -100
    camera.position.set(camPos.x, camPos.y, camPos.z)
    camera.rotation.y = camPos.x / -1000
    camera.rotation.x = camPos.y / 1000
    camera.rotation.z = (camPos.x - mouse.x * 400) / 2000
    renderer.render(scene, camera)
    requestAnimationFrame(render)
  }
  
  var vertexShader = [
    'varying vec2 vUv;',
    'void main()',
    '{',
    '  vUv = uv;',
    '  vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );',
    '  gl_Position = projectionMatrix * mvPosition;',
    '}'].join('')
  var fragmentShader = [
    'uniform float r;',
    'uniform float g;',
    'uniform float b;',
    'uniform float distanceZ;',
    'uniform float distanceX;',
    'uniform float pulse;',
    'uniform float speed;',
    'varying vec2 vUv;',
    'void main( void ) {',
    '  vec2 position = abs(-1.0 + 2.0 * vUv);',
    '  float edging = abs((pow(position.y, 5.0) + pow(position.x, 5.0)) / 2.0);',
    '  float perc = (0.2 * pow(speed + 1.0, 2.0) + edging * 0.8) * distanceZ * distanceX;',
    '  float red = r * perc + pulse;',
    '  float green = g * perc + pulse;',
    '  float blue = b * perc + pulse;',
    '  gl_FragColor = vec4(red, green, blue, 1.0);',
    '}'].join('')
  init()
  
  console.log('%c爱学习的小伙伴;', 'font-size:50px;color:blue')
  console.log('%c加我QQ1134512154', 'font-size:50px;color:red')
</script>
</body>
</html>
